/* 
 * Enterprise Library Extensions - DI + ORM.
 * Copyright (C) 2006
 *
 * GNU General Public License
 *
 * This program is free software; you can redistribute 
 * it and/or modify it under the terms of the GNU General Public License 
 * as published by the Free Software Foundation; either version 2 of the 
 * License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful, but 
 * WITHOUT ANY WARRANTY; without even the implied warranty of 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
 * See the GNU General Public License for more details.
 */
using System;
using System.Collections;
using System.Collections.Specialized;
using System.Runtime.Serialization;

namespace ELE.EnterpriseLibrary.Naming
{
	/// <summary>
  /// The Name interface represents a generic name -- an ordered sequence of components. 
  /// It can be a composite name (names that span multiple namespaces), or a compound name 
  /// (names that are used within individual hierarchical naming systems). 
  /// There can be different implementations of Name; for example, composite names, URLs, 
  /// or namespace-specific compound names. 
  /// The components of a name are numbered. The indexes of a name with N components range 
  /// from 0 up to, but not including, N. This range may be written as [0,N). The most 
  /// significant component is at index 0. An empty name has no components. 
  /// None of the methods in this interface accept null as a valid value for a parameter 
  /// that is a name or a name component. Likewise, methods that return a name or 
  /// name component never return null. 
  /// An instance of a Name may not be synchronized against concurrent multithreaded access 
  /// if that access is not read-only.
  /// NOTE: Objects that implement this interface must be serializable 
  /// </summary>
	public interface IName : ICloneable
	{
    /// <summary>
    /// Adds a component of a name to the specified position
    /// </summary>
    /// <param name="pPosition">position of the component in the name</param>
    /// <param name="pComponent">The component</param>
    /// <returns>the updated name (not a new one)</returns>
    IName Add(int pPosition, string pComponent);
    /// <summary>
    /// Adds a component of a name to the end of this name
    /// </summary>
    /// <param name="pComponent">The component</param>
    /// <returns>the updated name (not a new one)</returns>
    IName Add(string pComponent);
    /// <summary>
    /// Adds the components of a name to the specified position in this name
    /// </summary>
    /// <param name="pPosition">Start position of the components in the name</param>
    /// <param name="pName">The name to add</param>
    /// <returns>the updated name (not a new one)</returns>
    IName AddAll(int pPosition, IName pName);
    /// <summary>
    /// Adds the components of a name to the end of this name
    /// </summary>
    /// <param name="pName">The name to add</param>
    /// <returns>the updated name (not a new one)</returns>
    IName AddAll(IName pName);
    /// <summary>
    /// Compares this name with another name for order. 
    /// Returns a negative integer, zero, or a positive integer as this name is less than, 
    /// equal to, or greater than the given name.
    /// </summary>
    /// <param name="pObject">the non-null object to compare against</param>
    /// <returns>a negative integer, zero, or a positive integer as this name is less than, 
    /// equal to, or greater than the given name</returns>
    int CompareTo(object pObject);
    /// <summary>
    /// Determines whether this name ends with a specified suffix. A name n is a suffix if it 
    /// is equal to getSuffix(size()-n.size()).
    /// </summary>
    /// <param name="pName">the name to check</param>
    /// <returns>true if n is a suffix of this name, false otherwise</returns>
    bool EndsWith(IName pName);
    /// <summary>
    /// Determines whether this name starts with a specified prefix. A name n is a prefix if it 
    /// is equal to getPrefix(n.size()).
    /// </summary>
    /// <param name="pName">the name to check</param>
    /// <returns>true if n is a prefix of this name, false otherwise</returns>
    bool StartsWith(IName pName);
    /// <summary>
    /// Returns the name at the given position
    /// </summary>
    /// <param name="pPosition">the 0-based index of the component at which to stop. 
    /// Must be in the range [0,size()].</param>
    /// <returns>the component at index pPosition.</returns>
    string Get(int pPosition);
    /// <summary>
    /// Retrieves the components of this name as an enumeration of strings. The effect on 
    /// the enumeration of updates to this name is undefined. If the name has zero components, 
    /// an empty (non-null) enumeration is returned.
    /// </summary>
    /// <returns>an enumeration of the components of this name, each a string</returns>
    StringCollection GetAll();
    /// <summary>
    /// Creates a name whose components consist of a prefix of the components of this name. 
    /// Subsequent changes to this name will not affect the name that is returned and vice versa
    /// </summary>
    /// <param name="pPosition">the 0-based index of the component at which to stop. 
    /// Must be in the range [0,size()].</param>
    /// <returns>a name consisting of the components at indexes in the range [0,posn).</returns>
    IName GetPrefix(int pPosition);
    /// <summary>
    /// Creates a name whose components consist of a suffix of the components in this name. 
    /// Subsequent changes to this name do not affect the name that is returned and vice versa
    /// </summary>
    /// <param name="pPosition">the 0-based index of the component at which to start. 
    /// Must be in the range [0,size()].</param>
    /// <returns>a name consisting of the components at indexes in the range [posn,size()). 
    /// If posn is equal to size(), an empty name is returned</returns>
    IName GetSuffix(int pPosition);
    /// <summary>
    /// Determines whether this name is empty
    /// </summary>
    /// <returns>true if the name is empty or false otherwise</returns>
    bool IsEmpty { get; }
    /// <summary>
    /// Removes a component from this name. 
    /// The component of this name at the specified position is removed. 
    /// Components with indexes greater than this position are shifted down (toward index 0) by one.
    /// </summary>
    /// <param name="pPosition">the index of the component to remove. Must be in the range [0,size()).</param>
    /// <returns>the component removed (a String) </returns>
    /// <exception cref="NamingException"></exception>
    object Remove(int pPosition);
    /// <summary>
    /// Returns the number of components in this name.
    /// </summary>
    int Size { get; }
	}
}
